package com.hxzy.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxzy.common.annon.StopWatch;
import com.hxzy.dto.SysRoleSaveDTO;
import com.hxzy.dto.SysRoleSearchDTO;
import com.hxzy.entity.SysRole;
import com.hxzy.mapper.SysRoleMapper;
import com.hxzy.service.SysRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 角色
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {


    @Override
    public IPage<SysRole> search(SysRoleSearchDTO dto) {
        IPage page= PageDTO.of(dto.getPage(), dto.getSize());
        return this.baseMapper.search(page,dto);
    }

    @Override
    public List<BigDecimal> getRoleOwnMenuId(BigDecimal roleId) {
        return this.baseMapper.getRoleOwnMenuId(roleId);
    }

    /**
     * 新增操作
     * @param sysRoleSaveDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    @Override
    public boolean add(SysRoleSaveDTO sysRoleSaveDTO) {
        //1、先保存 sys_role表的数据
        SysRole  sysRole=new SysRole();
        //复制sysRoleSaveDTO的值到sysRole中
        BeanUtils.copyProperties(sysRoleSaveDTO, sysRole);
        sysRole.setDelFlag("0");

        boolean save = this.save(sysRole);

        //2、再保存SYS_ROLE_MENU表的数据
        if(save){
            if(sysRoleSaveDTO.getOwernMenus()!=null && sysRoleSaveDTO.getOwernMenus().length>0) {
                save= this.baseMapper.saveSysRoleMenu(sysRole.getRoleId(), sysRoleSaveDTO.getOwernMenus())>0;
            }
        }
        return save;
    }

    /**
     * 修改操作
     * @param sysRoleSaveDTO
     * @return
     */
    @StopWatch
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    @Override
    public boolean edit(SysRoleSaveDTO sysRoleSaveDTO) {
        //1、先更新 sys_role表的数据
        SysRole  sysRole=new SysRole();
        //复制sysRoleSaveDTO的值到sysRole中
        BeanUtils.copyProperties(sysRoleSaveDTO, sysRole);
        boolean save = this.updateById(sysRole);

        //(方案1，全删除)
        if(save){
            deleteAllAndInsert(sysRole,sysRoleSaveDTO);
        }

        //方案2，先求两个集合的交集，再分别求原数据库并集（删除的），再求本次修改集合的并集（要新增的）
//        if(save){
//           this.retainAndRemove(sysRole,sysRoleSaveDTO);
//        }
        return save;
    }

    @Override
    public Set<String> findRoleKeyByAdminId(Long adminId) {
        return this.baseMapper.findRoleKeyByAdminId(adminId);
    }

    /**
     *  (方案1，全删除)
     * @param dbRole
     * @param sysRoleSaveDTO
     * @return
     */
    private void deleteAllAndInsert(SysRole dbRole,SysRoleSaveDTO sysRoleSaveDTO){

        //2、再删除SYS_ROLE_MENU表的数据
        this.baseMapper.deleteSysRoleMenuByRoleId(dbRole.getRoleId());

        //3、再保存SYS_ROLE_MENU表的数据
        if(sysRoleSaveDTO.getOwernMenus()!=null && sysRoleSaveDTO.getOwernMenus().length>0) {
             this.baseMapper.saveSysRoleMenu(dbRole.getRoleId(), sysRoleSaveDTO.getOwernMenus());
        }
    }

    /**
     * 方案2，先求两个Set交集，再分别把交集与Set1求并集（要删除的）,再分别把交集与Set2求并集（新增的）
     * @param dbRole
     * @param sysRoleSaveDTO
     */
    private void retainAndRemove(SysRole dbRole,SysRoleSaveDTO sysRoleSaveDTO){
        //先查询到角色之前拥有的菜单
        Set<BigDecimal> dbSet = new HashSet<>(this.baseMapper.getRoleOwnMenuId(dbRole.getRoleId()));

        //本次修改集合
        if(sysRoleSaveDTO.getOwernMenus()!=null && sysRoleSaveDTO.getOwernMenus().length>0) {
            BigDecimal[] owernMenus = sysRoleSaveDTO.getOwernMenus();
            Set<BigDecimal> modiSet = new HashSet<>(Arrays.asList(owernMenus));

            //转Set 并求出交集
            Set<BigDecimal> retain=new HashSet<>(dbSet);
            retain.retainAll(modiSet);

            //再求数据库并集 (删除的)
            dbSet.removeAll(retain);
            if(dbSet.size()>0){
                this.baseMapper.removeSysRoleMenu(dbRole.getRoleId(),dbSet);
            }

            //再求本次并集 要新增的
            modiSet.removeAll(retain);
            if(modiSet.size()>0){
                this.baseMapper.saveSysRoleMenu(dbRole.getRoleId(),  modiSet.toArray(new BigDecimal[modiSet.size()]));
            }

        }else{
            //2、本次一个菜单都没有选中 删除SYS_ROLE_MENU表的数据角色相关的数据
            this.baseMapper.deleteSysRoleMenuByRoleId(dbRole.getRoleId());
        }
    }
}
